home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / small_eiffel.e < prev    next >
Text File  |  2000-03-25  |  37KB  |  1,280 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class SMALL_EIFFEL
  17.    --
  18.    -- Singleton object to handle general purpose information.
  19.    -- This singleton is shared via the GLOBALS.`small_eiffel' once function.
  20.    --
  21.  
  22. inherit GLOBALS;
  23.  
  24. creation make
  25.  
  26. feature
  27.  
  28.    copyright: STRING is
  29.       "-- SmallEiffel The GNU Eiffel Compiler -- Release (- 0.76Beta#1)--%N%
  30.       %-- Copyright (C), 1994-98 - LORIA - UHP - CRIN - INRIA - FRANCE --%N%
  31.       %-- Dominique COLNET and Suzanne COLLIN -    colnet@loria.fr     --%N%
  32.       %--                  http://SmallEiffel.loria.fr/                --%N";
  33.  
  34. feature {GC_HANDLER,C_PRETTY_PRINTER}
  35.  
  36.    root_procedure: RUN_FEATURE_3;
  37.  
  38. feature {NONE}
  39.  
  40.    make is
  41.       do
  42.       end;
  43.  
  44. feature
  45.  
  46.    loading_path: ARRAY[STRING] is
  47.       once
  48.          !!Result.with_capacity(32,1);
  49.          system_tools.read_loading_path_in(Result);
  50.       end;
  51.  
  52.    is_ready: BOOLEAN;
  53.          -- True when type inference algorithm is done : all
  54.          -- needed classes are loaded, `at_run_time' classes are
  55.          -- known, falling down is done, ...
  56.  
  57.    get_class(str: STRING): BASE_CLASS is
  58.       local
  59.          class_name: CLASS_NAME;
  60.       do
  61.          if base_class_dictionary.has(str) then
  62.             Result := base_class_dictionary.at(str);
  63.          else
  64.             !!class_name.unknown_position(str);
  65.             Result := class_name.base_class;
  66.          end;
  67.       ensure
  68.          Result /= Void
  69.       end;
  70.  
  71.    base_class(class_name: CLASS_NAME): BASE_CLASS is
  72.       require
  73.          class_name /= Void;
  74.       do
  75.          if base_class_dictionary.has(class_name.to_string) then
  76.             Result := base_class_dictionary.at(class_name.to_string);
  77.          elseif eiffel_parser.is_running then
  78.             fatal_error("Internal Error #1 in SMALL_EIFFEL.");
  79.          else
  80.             if parser_buffer_for(class_name.to_string) then
  81.                Result := eiffel_parser.analyse_class(class_name);
  82.                check
  83.                   Result /= Void
  84.                      implies
  85.                   base_class_dictionary.has(class_name.to_string);
  86.                end;
  87.             end;
  88.             if Result = Void then
  89.                eh.add_position(class_name.start_position);
  90.                fatal_error("Unable to load class.");
  91.             end;
  92.          end;
  93.       end;
  94.  
  95.    load_class(name: STRING): BASE_CLASS is
  96.          -- Try to load a class using it's `name' (ie. not the corresponding 
  97.          -- file path).
  98.       require
  99.          name = string_aliaser.item(name);
  100.          not eiffel_parser.is_running
  101.       local
  102.          class_name: CLASS_NAME;
  103.       do
  104.          check
  105.             not name.has('.');
  106.             not name.has('/');
  107.             not name.has('\');
  108.             not name.has(' ');
  109.             not name.has(':');
  110.          end;
  111.          !!class_name.unknown_position(name);
  112.          if parser_buffer_for(name) then
  113.             Result := eiffel_parser.analyse_class(class_name);
  114.             if Result = Void then
  115.                fatal_error("Cannot load class.");
  116.             end;
  117.          else
  118.             fatal_error("Cannot find class.");
  119.          end;
  120.       end;
  121.  
  122.    same_base_feature(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
  123.          -- True when all `dynamic' features of `r' have excately the same 
  124.          -- final name and refer exactely to the same `base_feature'.
  125.       require
  126.          is_ready and r.count > 1
  127.       local
  128.          i: INTEGER;
  129.          f: E_FEATURE;
  130.          dyn_rf: RUN_FEATURE;
  131.          rc: RUN_CLASS;
  132.       do
  133.          from
  134.             Result := true;
  135.             i := r.upper;
  136.             f := up_rf.base_feature;
  137.          until
  138.             not Result or else i = 0
  139.          loop
  140.             rc := r.item(i);
  141.             dyn_rf := rc.dynamic(up_rf);
  142.             if f = dyn_rf.base_feature then
  143.                if dyn_rf.name.to_string /= up_rf.name.to_string then
  144.                   Result := false;
  145.                end;
  146.             else
  147.                Result := false;
  148.             end;
  149.             i := i - 1;
  150.          end;
  151.       end;
  152.  
  153.    stupid_switch(t: TYPE; r: ARRAY[RUN_CLASS]): BOOLEAN is
  154.          -- True when `t' drives exactely to the same `t.run_type' for all `r'.
  155.       require
  156.          is_ready
  157.       do
  158.          if r = Void then
  159.             Result := true;
  160.          elseif r.count = 1 then
  161.             Result := true;
  162.          else
  163.             Result := t.stupid_switch(r);
  164.          end;
  165.       end;
  166.  
  167. feature {PRETTY}
  168.  
  169.    re_load_class(e_class: BASE_CLASS): BOOLEAN is
  170.       require
  171.          e_class /= Void;
  172.       local
  173.          name: STRING;
  174.          new_class: like e_class;
  175.       do
  176.          name := e_class.name.to_string;
  177.          check
  178.             base_class_dictionary.has(name);
  179.          end;
  180.          base_class_dictionary.remove(name);
  181.          new_class := load_class(name);
  182.          Result := new_class /= Void;
  183.       end;
  184.  
  185. feature {BASE_CLASS}
  186.  
  187.    add_base_class(bc: BASE_CLASS) is
  188.       require
  189.          bc /= Void
  190.       local
  191.          name: STRING;
  192.       do
  193.          name := bc.name.to_string
  194.          check
  195.             not name.is_empty;
  196.             not base_class_dictionary.has(name);
  197.          end;
  198.          base_class_dictionary.put(bc,name);
  199.          incr_magic_count;
  200.       ensure
  201.          base_class_dictionary.has(bc.name.to_string);
  202.       end;
  203.  
  204. feature {FINDER}
  205.  
  206.    find_path_for(arg: STRING): STRING is
  207.       do
  208.          if parser_buffer_for(arg) then
  209.             Result := parser_buffer.path;
  210.          end;
  211.          parser_buffer.unset_is_ready;
  212.       end;
  213.  
  214. feature {NONE}
  215.  
  216.    parser_buffer_path: STRING is
  217.       once
  218.          !!Result.make(256);
  219.       end;
  220.  
  221.    parser_buffer_for(name: STRING): BOOLEAN is
  222.          -- SmallEiffel algorithm for searching classes on the disk.
  223.          -- When Result, `parser_buffer' is ready to be used.
  224.       require
  225.          name /= Void;
  226.          not parser_buffer.is_ready
  227.       local
  228.          i: INTEGER;
  229.       do
  230.          tmp_tail.copy(name);
  231.          tmp_tail.to_lower;
  232.          if not tmp_tail.has_suffix(eiffel_suffix) then
  233.             tmp_tail.append(eiffel_suffix);
  234.          end;
  235.          from
  236.             i := loading_path.lower;
  237.          until
  238.             i > loading_path.upper or else Result
  239.          loop
  240.             parser_buffer_path.copy(loading_path.item(i));
  241.             parser_buffer_path.append(tmp_tail);
  242.             parser_buffer.load_file(parser_buffer_path);
  243.             Result := parser_buffer.is_ready;
  244.             i := i + 1;
  245.          end;
  246.          if not Result and then rename_dictionary.has(tmp_tail) then
  247.             parser_buffer_path.copy(rename_dictionary.at(tmp_tail));
  248.             parser_buffer.load_file(parser_buffer_path);
  249.             if parser_buffer.is_ready then
  250.                Result := true;
  251.             else
  252.                echo.w_put_string("Bad %"rename.se%" file.%NCannot open %"");
  253.                echo.w_put_string(parser_buffer_path);
  254.                echo.w_put_string(fz_03);
  255.                die_with_code(exit_failure_code);
  256.             end;
  257.          end;
  258.          if not Result then
  259.             tmp_tail.copy(name);
  260.             if not tmp_tail.has_suffix(eiffel_suffix) then
  261.                tmp_tail.append(eiffel_suffix);
  262.             end;
  263.             from
  264.                i := loading_path.lower;
  265.             until
  266.                i > loading_path.upper or else Result
  267.             loop
  268.                parser_buffer_path.copy(loading_path.item(i));
  269.                parser_buffer_path.append(tmp_tail);
  270.                parser_buffer.load_file(parser_buffer_path);
  271.                Result := parser_buffer.is_ready;
  272.                i := i + 1;
  273.             end;
  274.          end;
  275.          if not Result then
  276.             echo.w_put_string("Unable to find file for class %"");
  277.             echo.w_put_string(name);
  278.             echo.w_put_string("%". ");
  279.             parser_buffer_path.clear;
  280.             append_loading_path_in(parser_buffer_path);
  281.             echo.w_put_string(parser_buffer_path);
  282.          end;
  283.       ensure
  284.          Result implies parser_buffer.is_ready
  285.       end;
  286.  
  287.    rename_dictionary: DICTIONARY[STRING,STRING] is
  288.          -- Handling of "rename.se" files.
  289.       local
  290.          i: INTEGER;
  291.          full_name, short_name: STRING;
  292.       once
  293.          from
  294.             !!Result.make;
  295.             i := 1;
  296.          until
  297.             i > loading_path.upper
  298.          loop
  299.             tmp_path.copy(loading_path.item(i));
  300.             tmp_path.append("rename.se");
  301.             echo.sfr_connect(tmp_file_read,tmp_path);
  302.             if tmp_file_read.is_connected then
  303.                from
  304.                until
  305.                   tmp_file_read.end_of_input
  306.                loop
  307.                   tmp_file_read.read_word;
  308.                   full_name := tmp_file_read.last_string.twin;
  309.                   tmp_file_read.read_word;
  310.                   short_name := tmp_file_read.last_string.twin;
  311.                   short_name.prepend(loading_path.item(i));
  312.                   if Result.has(full_name) then
  313.                      echo.w_put_string("Multiple entry for %"");
  314.                      echo.w_put_string(full_name);
  315.                      echo.w_put_string("%" in %"rename.se%" files.%N%
  316.                                            %Clash for %N%"");
  317.                      echo.w_put_string(short_name);
  318.                      echo.w_put_string("%" and %N%"");
  319.                      echo.w_put_string(Result.at(full_name));
  320.                      echo.w_put_string(".%N");
  321.                      die_with_code(exit_failure_code);
  322.                   end;
  323.                   Result.put(short_name,full_name)
  324.                   tmp_file_read.skip_separators;
  325.                end;
  326.                tmp_file_read.disconnect;
  327.             end;
  328.             i := i + 1;
  329.          end;
  330.       end;
  331.  
  332. feature
  333.  
  334.    short_flag: BOOLEAN;
  335.          -- True when command `short' is running.
  336.  
  337.    pretty_flag: BOOLEAN;
  338.          -- True when command `pretty' is running.
  339.  
  340. feature {SHORT}
  341.  
  342.    set_short_flag is
  343.       do
  344.          short_flag := true;
  345.       end;
  346.  
  347. feature {PRETTY}
  348.  
  349.    set_pretty_flag is
  350.       do
  351.          pretty_flag := true;
  352.       end;
  353.  
  354. feature
  355.  
  356.    is_used(cn: STRING): BOOLEAN is
  357.          -- Is the base class `cn' used (loaded) ?
  358.       do
  359.          Result := base_class_dictionary.has(cn);
  360.       end;
  361.  
  362.    run_class(t: TYPE): RUN_CLASS is
  363.       require
  364.          t.run_type = t
  365.       local
  366.          run_string: STRING;
  367.       do
  368.          run_string := t.run_time_mark;
  369.          if run_class_dictionary.has(run_string) then
  370.             Result := run_class_dictionary.at(run_string);
  371.          else
  372.             !!Result.make(t);
  373.             check
  374.                run_class_dictionary.has(run_string);
  375.             end;
  376.          end;
  377.       ensure
  378.          Result /= Void
  379.       end;
  380.  
  381. feature
  382.  
  383.    base_class_count: INTEGER is
  384.          -- Total number of base class actually loaded.
  385.       do
  386.          Result := base_class_dictionary.count;
  387.       end;
  388.  
  389. feature
  390.  
  391.    compile_to_c is
  392.          -- Produce C code for `root_class'/`procedure'.
  393.       local
  394.          root_class, procedure: STRING;
  395.          rc: RUN_CLASS;
  396.          run_count: INTEGER;
  397.          i: INTEGER;
  398.          gc_flag: BOOLEAN;
  399.       do
  400.          root_class := run_control.root_class;
  401.          procedure := run_control.root_procedure;
  402.          get_started(root_class,procedure);
  403.          if nb_errors = 0 then
  404.             check
  405.                root_procedure /= Void
  406.             end;
  407.             cpp.get_started;
  408.             cpp.swap_on_h;
  409.             gc_flag := not gc_handler.is_off;
  410.             -- ---------------------------------------------------------
  411.             cpp.put_string("%N/* --- Mangling Table Start ---%N");
  412.             from
  413.                i := 1;
  414.             until
  415.                i > run_class_dictionary.count
  416.             loop
  417.                rc := run_class_dictionary.item(i);
  418.                if rc.at_run_time then
  419.                   run_count := run_count + 1;
  420.                end;
  421.                rc.demangling;
  422.                i := i + 1;
  423.             end;
  424.             cpp.put_string(" --- Mangling Table End --- */%N");
  425.             -- ---------------------------------------------------------
  426.             from
  427.                cpp.put_comment_line("C Header Pass 1 :");
  428.                i := 1;
  429.             until
  430.                i > run_class_dictionary.count
  431.             loop
  432.                rc := run_class_dictionary.item(i);
  433.                rc.c_header_pass1;
  434.                i := i + 1;
  435.             end;
  436.             -- ---------------------------------------------------------
  437.             from
  438.                cpp.put_comment_line("C Header Pass 2 :");
  439.                i := 1;
  440.             until
  441.                i > run_class_dictionary.count
  442.             loop
  443.                rc := run_class_dictionary.item(i);
  444.                rc.c_header_pass2;
  445.                i := i + 1;
  446.             end;
  447.             -- ---------------------------------------------------------
  448.             from
  449.                cpp.put_comment_line("C Header Pass 3 :");
  450.                i := 1;
  451.             until
  452.                i > run_class_dictionary.count
  453.             loop
  454.                rc := run_class_dictionary.item(i);
  455.                rc.c_header_pass3;
  456.                i := i + 1;
  457.             end;
  458.             -- ---------------------------------------------------------
  459.             from
  460.                cpp.put_comment_line("C Header Pass 4 :");
  461.                i := 1;
  462.             until
  463.                i > run_class_dictionary.count
  464.             loop
  465.                rc := run_class_dictionary.item(i);
  466.                rc.c_header_pass4;
  467.                i := i + 1;
  468.             end;
  469.             -- Force definition of T9 and T7 :
  470.             if not run_class_dictionary.has(as_native_array_character) then
  471.                cpp.put_string("typedef char* T9;%N");
  472.                if run_control.no_check then
  473.                   cpp.put_c_function("void se_prinT9(T9*o)",
  474.                                      "printf(%"NATIVE_ARRAY[STRING]#%%p\n%",*o);");
  475.                end;
  476.             end;
  477.             manifest_string_pool.c_define1(string_at_run_time);
  478.             cpp.customize_runtime(basic_sys_runtime);
  479.             -- ---------------------------------------------------------
  480.             if gc_flag then
  481.                gc_handler.define1;
  482.             end;
  483.             -- ---------------------------------------------------------
  484.             compile_routines;
  485.             cpp.cecil_define;
  486.             -- ---------------------------------------------------------
  487.             cpp.define_main(root_procedure);
  488.             manifest_string_pool.c_define2(string_at_run_time);
  489.             compile_registered_for_c_define;
  490.             address_of_pool.c_define;
  491.             if gc_flag then
  492.                gc_handler.define2;
  493.             end;
  494.             manifest_array_pool.c_define;
  495.             switch_collection.c_define;
  496.             cpp.define_used_basics;
  497.             debug
  498.                echo.put_string("Very Final magic_count : ");
  499.                echo.put_integer(magic_count);
  500.                echo.put_character('%N');
  501.             end;
  502.             cpp.write_make_file;
  503.          else
  504.             eh.append("Cannot produce C code.");
  505.             eh.print_as_error;
  506.          end;
  507.       end;
  508.  
  509.    compile_to_jvm is
  510.          -- Produce Java Byte Code for `root_class'/`procedure'.
  511.       local
  512.          root_class, procedure: STRING;
  513.          rc: RUN_CLASS;
  514.          run_count, i: INTEGER;
  515.       do
  516.          root_class := run_control.root_class;
  517.          procedure := run_control.root_procedure;
  518.          get_started(root_class,procedure);
  519.          if nb_errors = 0 then
  520.             jvm.prepare_output_directory;
  521.             from
  522.                i := 1;
  523.             until
  524.                i > run_class_dictionary.count
  525.             loop
  526.                rc := run_class_dictionary.item(i);
  527.                if rc.at_run_time then
  528.                   run_count := run_count + 1;
  529.                   rc.compile_to_jvm;
  530.                end;
  531.                i := i + 1;
  532.             end;
  533.             echo.print_count("Used Type",run_count);
  534.             jvm.write_jvm_root_class;
  535.             jvm.write_main_class(root_procedure);
  536.          else
  537.             eh.append("Cannot produce Java Byte Code.");
  538.             eh.print_as_error;
  539.          end;
  540.       end;
  541.  
  542. feature {NONE}
  543.  
  544.    base_class_dictionary: DICTIONARY[BASE_CLASS,STRING] is
  545.          -- When looking for a BASE_CLASS using the name of
  546.          -- base class (ie FOO[BAR] is stored at key "FOO").
  547.       once
  548.          !!Result.with_capacity(2048);
  549.       end;
  550.  
  551. feature
  552.  
  553.    magic_count: INTEGER;
  554.          -- Grow each time a new run class is added, each time a new
  555.          -- class is loaded, each time a new feature is checked,
  556.          -- each time ...
  557.          -- Thus when `magic_count' stops growing, we are really
  558.          -- ready to run :-).
  559.  
  560. feature {RUN_CLASS,RUN_FEATURE,ASSERTION_COLLECTOR,SWITCH_COLLECTION}
  561.  
  562.    incr_magic_count is
  563.       do
  564.          magic_count := magic_count + 1;
  565.       end;
  566.  
  567. feature {BASE_CLASS,RUN_CLASS,GC_HANDLER}
  568.  
  569.    run_class_dictionary: DICTIONARY[RUN_CLASS,STRING] is
  570.       once
  571.          !!Result.with_capacity(2048);
  572.       end;
  573.  
  574. feature {CALL_PROC_CALL}
  575.  
  576.    run_class_with(run_time_mark: STRING): RUN_CLASS is
  577.       do
  578.          if run_class_dictionary.has(run_time_mark) then
  579.             Result := run_class_dictionary.at(run_time_mark);
  580.          end;
  581.       end;
  582.  
  583. feature {RUN_CLASS}
  584.  
  585.    is_tagged(rc: RUN_CLASS): BOOLEAN is
  586.       require
  587.          is_ready;
  588.          rc.at_run_time;
  589.          rc.current_type.is_reference;
  590.          run_control.boost
  591.       local
  592.          i, up: INTEGER;
  593.          r: ARRAY[RUN_CLASS];
  594.          rcd: like run_class_dictionary;
  595.          rc2: RUN_CLASS;
  596.       do
  597.          from
  598.             i := 1;
  599.             rcd := run_class_dictionary;
  600.             up := rcd.count;
  601.          until
  602.             Result or else i > up
  603.          loop
  604.             rc2 := rcd.item(i);
  605.             r := rc2.running;
  606.             if r = Void then
  607.             elseif r.fast_has(rc) then
  608.                Result := r.count > 1;
  609.             end;
  610.             i := i + 1;
  611.          end;
  612.       end;
  613.  
  614.    memory_class_used: BASE_CLASS is
  615.          -- The MEMORY class when used or Void when this class is not
  616.          -- in the live code..
  617.       do
  618.          if base_class_dictionary.has(as_memory) then
  619.             Result := base_class_dictionary.at(as_memory);
  620.          end;
  621.       end;
  622.  
  623. feature {NONE}
  624.  
  625.    get_started(root_class_name, procedure_name: STRING) is
  626.          -- Get started to compile using creation `procedure_name'
  627.          -- of base class `root_class_name'.
  628.       require
  629.          not root_class_name.is_empty;
  630.          not procedure_name.is_empty
  631.       local
  632.          root_proc_name: SIMPLE_FEATURE_NAME;
  633.          root: BASE_CLASS;
  634.          root_proc: PROCEDURE;
  635.          root_type: TYPE;
  636.          magic: INTEGER;
  637.       do
  638.          echo.put_string(copyright);
  639.          if run_control.no_check then
  640.             run_control.set_generator_used;
  641.             run_control.set_generating_type_used;
  642.          end;
  643.          echo.put_string("Parsing :%N");
  644.          root := load_class(root_class_name);
  645.          if root = Void then
  646.             eh.append("Cannot load root class ");
  647.             eh.append(root_class_name);
  648.             eh.append(fz_dot);
  649.             eh.print_as_error;
  650.          else
  651.             root_proc_name := root.root_procedure_name(procedure_name);
  652.             root_proc := root.root_procedure(root_proc_name);
  653.          end;
  654.          if nb_errors = 0 then
  655.             if root_proc.arguments /= Void then
  656.                eh.add_position(root_proc.start_position);
  657.                eh.append("Creation procedure ");
  658.                eh.append(procedure_name);
  659.                eh.append(" must not have arguments.");
  660.                eh.print_as_error;
  661.             end;
  662.          end;
  663.          if nb_errors = 0 then
  664.             root_type := root.run_class.current_type;
  665.          end;
  666.          if nb_errors = 0 then
  667.             root_procedure := root_proc.to_run_feature(root_type,root_proc_name);
  668.          end;
  669.          if nb_errors = 0 then
  670.             echo.put_string("Starting Falling Down (");
  671.             echo.put_integer(magic_count);
  672.             echo.put_string(em1);
  673.             from
  674.                falling_down;
  675.                cecil_pool.fill_up;
  676.             until
  677.                magic = magic_count or else nb_errors > 0
  678.             loop
  679.                magic := magic_count;
  680.                falling_down;
  681.             end;
  682.             echo.put_string("End of Falling Down (");
  683.             echo.put_integer(magic_count);
  684.             echo.put_string(em1);
  685.          end;
  686.          if nb_errors = 0 then
  687.             echo.put_string("Starting AFD Check (");
  688.             echo.put_integer(magic_count);
  689.             echo.put_string(em1);
  690.             from
  691.                afd_check;
  692.             until
  693.                magic = magic_count or else nb_errors > 0
  694.             loop
  695.                magic := magic_count;
  696.                afd_check;
  697.             end;
  698.             check_for_deferred;
  699.             check_generic_formal_arguments;
  700.             switch_collection.afd;
  701.             echo.put_string("Before conversion handling (");
  702.             echo.put_integer(magic_count);
  703.             echo.put_string(em1);
  704.             conversion_handler.finish_falling_down;
  705.             echo.put_string("After conversion handling (");
  706.             echo.put_integer(magic_count);
  707.             echo.put_string(em1);
  708.             from
  709.             until
  710.                magic = magic_count or else nb_errors > 0
  711.             loop
  712.                magic := magic_count;
  713.                falling_down;
  714.             end;
  715.             echo.put_string("End of AFD Check (");
  716.             echo.put_integer(magic_count);
  717.             echo.put_string(em1);
  718.          end;
  719.          if not eh.is_empty then
  720.             eh.append("Internal Warning #1 (Error Handler Not Empty) : ");
  721.             eh.print_as_warning;
  722.          end;
  723.          if nb_errors = 0 then
  724.             is_ready := true;
  725.             echo.print_count("Loaded Classe",base_class_dictionary.count);
  726.          end;
  727.       ensure
  728.          nb_errors = 0 implies root_procedure /= Void
  729.       end;
  730.  
  731. feature -- To add more Context for some `to_runnable' :
  732.  
  733.    top_rf: RUN_FEATURE is
  734.       do
  735.          Result := stack_rf.item(top);
  736.       end;
  737.  
  738.    push(rf: RUN_FEATURE) is
  739.       do
  740.          top := top + 1;
  741.          stack_rf.force(rf,top);
  742.       end;
  743.  
  744.    pop is
  745.       do
  746.          check
  747.             1 <= top;
  748.          end;
  749.          top := top - 1;
  750.       ensure
  751.          old(top) = top + 1
  752.       end;
  753.  
  754. feature {NONE}
  755.  
  756.    stack_rf: ARRAY[RUN_FEATURE] is
  757.       once
  758.          !!Result.make(1,50);
  759.       end;
  760.  
  761.    top: INTEGER;
  762.  
  763. feature {NONE}
  764.  
  765.    falling_down is
  766.       local
  767.          rc: RUN_CLASS;
  768.          i: INTEGER;
  769.       do
  770.          if run_control.generator_used then
  771.             type_string.set_at_run_time;
  772.          end;
  773.          manifest_string_pool.falling_down;
  774.          address_of_pool.falling_down;
  775.          from
  776.             i := 1;
  777.          until
  778.             i > run_class_dictionary.count
  779.          loop
  780.             rc := run_class_dictionary.item(i);
  781.             rc.falling_down;
  782.             i := i + 1;
  783.          end;
  784.       end;
  785.  
  786.    afd_check is
  787.       local
  788.          rc: RUN_CLASS;
  789.          i: INTEGER;
  790.       do
  791.          from
  792.             i := 1;
  793.          until
  794.             i > run_class_dictionary.count
  795.          loop
  796.             rc := run_class_dictionary.item(i);
  797.             rc.afd_check;
  798.             i := i + 1;
  799.          end;
  800.       end;
  801.  
  802. feature {RUN_FEATURE_9}
  803.  
  804.    afd_check_deferred(rf9: RUN_FEATURE_9) is
  805.       do
  806.          if not rf9_memory.fast_has(rf9) then
  807.             rf9_memory.add_last(rf9);
  808.          end;
  809.       end;
  810.  
  811. feature {NONE}
  812.  
  813.    rf9_memory: FIXED_ARRAY[RUN_FEATURE_9] is
  814.       once
  815.          !!Result.with_capacity(1024);
  816.       end;
  817.  
  818.    check_for_deferred is
  819.       local
  820.          i: INTEGER;
  821.          rf9: RUN_FEATURE;
  822.          rc: RUN_CLASS;
  823.       do
  824.          from
  825.             i := rf9_memory.upper
  826.             echo.print_count("Deferred Routine",i+1);
  827.          until
  828.             i < 0
  829.          loop
  830.             rf9 := rf9_memory.item(i);
  831.             rc := rf9.current_type.run_class;
  832.             if rc.at_run_time then
  833.                eh.append(rf9.name.to_string);
  834.                eh.append(" is a deferred feature in ");
  835.                eh.append(rf9.current_type.written_mark);
  836.                warning(rf9.start_position,fz_dot);
  837.             end;
  838.             i := i - 1;
  839.          end;
  840.       end;
  841.  
  842.    check_generic_formal_arguments is
  843.       local
  844.          i: INTEGER;
  845.       do
  846.          from
  847.             i := 1;
  848.          until
  849.             i > base_class_dictionary.count
  850.          loop
  851.             base_class_dictionary.item(i).check_generic_formal_arguments;
  852.             i := i + 1;
  853.          end;
  854.       end;
  855.  
  856. feature {ID_PROVIDER}
  857.  
  858.    id_extra_information(sfw: STD_FILE_WRITE; name: STRING) is
  859.       local
  860.          bc: BASE_CLASS;
  861.          rc: RUN_CLASS;
  862.          path: STRING;
  863.      do
  864.     if name = as_none then
  865.     elseif run_class_dictionary.has(name) then
  866.            rc := run_class_dictionary.at(name);
  867.            bc := rc.base_class;
  868.         elseif base_class_dictionary.has(name) then
  869.            bc := base_class_dictionary.at(name);
  870.         else
  871.         end;
  872.         if bc /= Void then
  873.            sfw.put_string("class-path: %"");
  874.            path := bc.path;
  875.            sfw.put_string(path);
  876.            sfw.put_character('%"');
  877.            sfw.put_character(' ');
  878.            bc.id_extra_information(sfw);
  879.         end;
  880.         if rc /= Void then
  881.            rc.id_extra_information(sfw);
  882.         end;
  883.      end;
  884.  
  885. feature {C_PRETTY_PRINTER}
  886.  
  887.    define_extern_tables is
  888.       require
  889.          cpp.on_c
  890.       local
  891.          size: INTEGER;
  892.       do
  893.          size := id_provider.max_id + 1;
  894.          cpp.macro_def("SE_MAXID",size);
  895.          if run_control.generator_used then
  896.             cpp.put_extern4(fz_t7_star,"g",size);
  897.          end;
  898.          if run_control.generating_type_used then
  899.             cpp.put_extern4(fz_t7_star,"t",size);
  900.          end;
  901.          if run_control.no_check then
  902.             cpp.put_extern4("char*","p",size);
  903.             c_code.copy("void(*se_prinT[");
  904.             size.append_in(c_code);
  905.             c_code.append("])(void**)");
  906.             cpp.put_extern1(c_code);
  907.          end;
  908.       end;
  909.  
  910.    initialize_path_table is
  911.       require
  912.          run_control.no_check;
  913.          cpp.on_c;
  914.       local
  915.          i: INTEGER;
  916.          bc: BASE_CLASS;
  917.          rc: RUN_CLASS;
  918.       do
  919.          from
  920.             -- *** Add the current path for Jacob Navia. ***
  921.             cpp.put_string("p[0]=%"???%";%N");
  922.             i := 1;
  923.          until
  924.             i > base_class_dictionary.count
  925.          loop
  926.             bc := base_class_dictionary.item(i);
  927.             cpp.put_string("p[");
  928.             cpp.put_integer(bc.id);
  929.             cpp.put_string("]=");
  930.             cpp.put_string_c(bc.path);
  931.             cpp.put_string(fz_00);
  932.             i := i + 1;
  933.          end;
  934.          from
  935.             i := 1;
  936.          until
  937.             i > run_class_dictionary.count
  938.          loop
  939.             rc := run_class_dictionary.item(i);
  940.             if rc.at_run_time then
  941.                cpp.put_string("se_prinT[");
  942.                cpp.put_integer(rc.id);
  943.                cpp.put_string("]=((void(*)(void**))se_prinT");
  944.                cpp.put_integer(rc.id);
  945.                cpp.put_string(");%N");
  946.                if rc.current_type.is_generic then
  947.                   cpp.put_string("p[");
  948.                   cpp.put_integer(rc.id);
  949.                   cpp.put_string("]=p[");
  950.                   cpp.put_integer(rc.base_class.id);
  951.                   cpp.put_string("];%N");
  952.                end;
  953.             end;
  954.             i := i + 1;
  955.          end;
  956.       ensure
  957.          cpp.on_c;
  958.       end;
  959.  
  960.    initialize_generator is
  961.       require
  962.          cpp.on_c
  963.       local
  964.          i: INTEGER;
  965.          bc: BASE_CLASS;
  966.          rc: RUN_CLASS;
  967.       do
  968.          from
  969.             i := 1;
  970.          until
  971.             i > base_class_dictionary.count
  972.          loop
  973.             bc := base_class_dictionary.item(i);
  974.             cpp.put_array1('g',bc.id);
  975.             cpp.put_character('=');
  976.             cpp.put_se_string_from_external_copy(bc.name.to_string);
  977.             cpp.put_string(fz_00);
  978.             i := i + 1;
  979.          end;
  980.          from
  981.             i := 1;
  982.          until
  983.             i > run_class_dictionary.count
  984.          loop
  985.             rc := run_class_dictionary.item(i);
  986.             if rc.at_run_time then
  987.                bc := rc.base_class;
  988.                if bc.name.to_string /= rc.current_type.run_time_mark then
  989.                   cpp.put_array1('g',rc.id);
  990.                   cpp.put_character('=');
  991.                   cpp.put_array1('g',bc.id);
  992.                   cpp.put_string(fz_00);
  993.                end;
  994.             end;
  995.             i := i + 1;
  996.          end;
  997.       ensure
  998.          cpp.on_c;
  999.       end;
  1000.  
  1001.    initialize_generating_type is
  1002.       require
  1003.          cpp.on_c;
  1004.       local
  1005.          i: INTEGER;
  1006.          rc: RUN_CLASS;
  1007.          bc: BASE_CLASS;
  1008.          rtm: STRING;
  1009.       do
  1010.          from
  1011.             i := 1;
  1012.          until
  1013.             i > run_class_dictionary.count
  1014.          loop
  1015.             rc := run_class_dictionary.item(i);
  1016.             if rc.at_run_time then
  1017.                cpp.put_array1('t',rc.id);
  1018.                cpp.put_character('=');
  1019.                bc := rc.base_class;
  1020.                rtm := rc.current_type.run_time_mark
  1021.                if bc.name.to_string /= rtm then
  1022.                   cpp.put_se_string_from_external_copy(rtm);
  1023.                else
  1024.                   cpp.put_array1('g',rc.id);
  1025.                end;
  1026.                cpp.put_string(fz_00);
  1027.             end;
  1028.             i := i + 1;
  1029.          end;
  1030.       ensure
  1031.          cpp.on_c;
  1032.       end;
  1033.  
  1034. feature {NONE}
  1035.  
  1036.    compile_routines is
  1037.          -- Try to give the best order to the C output.
  1038.       local
  1039.          rc, rc_string: RUN_CLASS;
  1040.          ct: TYPE;
  1041.          deep, i: INTEGER;
  1042.          stop: BOOLEAN;
  1043.          bcn: STRING;
  1044.       do
  1045.          echo.put_string("Compiling/Sorting routines for ");
  1046.          echo.put_integer(run_class_dictionary.count);
  1047.          echo.put_string(" run classes :%N");
  1048.          cpp.swap_on_c;
  1049.          from
  1050.             i := 1;
  1051.          until
  1052.             i > run_class_dictionary.count
  1053.          loop
  1054.             rc := run_class_dictionary.item(i);
  1055.             ct := rc.current_type;
  1056.             if ct.is_basic_eiffel_expanded then
  1057.                rc.compile_to_c(0);
  1058.             elseif ct.is_string then
  1059.                rc_string := rc;
  1060.             end;
  1061.             i := i + 1;
  1062.          end;
  1063.          from
  1064.             i := 1;
  1065.          until
  1066.             i > run_class_dictionary.count
  1067.          loop
  1068.             rc := run_class_dictionary.item(i);
  1069.             ct := rc.current_type;
  1070.             if ct.is_bit then
  1071.                rc.compile_to_c(0);
  1072.             end;
  1073.             i := i + 1;
  1074.          end;
  1075.          from
  1076.             i := 1;
  1077.          until
  1078.             i > run_class_dictionary.count
  1079.          loop
  1080.             rc := run_class_dictionary.item(i);
  1081.             bcn := rc.base_class_name.to_string;
  1082.             if as_native_array = bcn then
  1083.                rc.compile_to_c(0);
  1084.             end;
  1085.             i := i + 1;
  1086.          end;
  1087.          if rc_string /= Void then
  1088.             rc_string.compile_to_c(0);
  1089.          end;
  1090.          from
  1091.             i := 1;
  1092.          until
  1093.             i > run_class_dictionary.count
  1094.          loop
  1095.             rc := run_class_dictionary.item(i);
  1096.             ct := rc.current_type;
  1097.             bcn := ct.base_class_name.to_string;
  1098.             if as_array = bcn or else as_fixed_array = bcn then
  1099.                rc.compile_to_c(0);
  1100.             end;
  1101.             i := i + 1;
  1102.          end;
  1103.          from
  1104.             i := 1;
  1105.          until
  1106.             i > run_class_dictionary.count
  1107.          loop
  1108.             rc := run_class_dictionary.item(i);
  1109.             ct := rc.current_type;
  1110.             if ct.is_generic then
  1111.                rc.compile_to_c(0);
  1112.             end;
  1113.             i := i + 1;
  1114.          end;
  1115.          from -- General sorting :
  1116.             deep := 6;
  1117.          until
  1118.             stop
  1119.          loop
  1120.             from
  1121.                stop := true;
  1122.                i := 1;
  1123.             until
  1124.                i > run_class_dictionary.count
  1125.             loop
  1126.                rc := run_class_dictionary.item(i);
  1127.                if not rc.compile_to_c_done then
  1128.                   stop := false;
  1129.                   rc.compile_to_c(deep);
  1130.                end;
  1131.                i := i + 1;
  1132.             end;
  1133.             deep := deep - 1;
  1134.          end;
  1135.       end;
  1136.  
  1137. feature {NONE}
  1138.  
  1139.    tmp_tail: STRING is
  1140.       once
  1141.          !!Result.make(128);
  1142.       end;
  1143.  
  1144. feature {NONE}
  1145.  
  1146.    em1: STRING is " items).%N";
  1147.  
  1148. feature {NONE}
  1149.  
  1150.    append_loading_path_in(str: STRING) is
  1151.       do
  1152.          system_tools.append_lp_in(str,loading_path);
  1153.       end;
  1154.  
  1155. feature {NONE}
  1156.  
  1157.    c_code: STRING is
  1158.       once
  1159.          !!Result.make(128);
  1160.       end;
  1161.  
  1162. feature {NONE}
  1163.  
  1164.    registered_for_c_define: FIXED_ARRAY[RUN_FEATURE_3] is
  1165.       once
  1166.          !!Result.with_capacity(512);
  1167.       end;
  1168.  
  1169.    compile_registered_for_c_define is
  1170.       local
  1171.          i: INTEGER;
  1172.       do
  1173.          from
  1174.             i := registered_for_c_define.upper;
  1175.          until
  1176.             i < 0
  1177.          loop
  1178.             registered_for_c_define.item(i).c_define;
  1179.             i := i - 1;
  1180.          end;
  1181.       end;
  1182.  
  1183. feature {RUN_FEATURE_3}
  1184.  
  1185.    register_for_c_define(rf: RUN_FEATURE_3) is
  1186.       require
  1187.          rf /= Void
  1188.       do
  1189.          registered_for_c_define.add_last(rf);
  1190.       end;
  1191.  
  1192. feature {RUN_FEATURE_8}
  1193.    
  1194.    register_sys_runtime_basic_of(name: STRING) is
  1195.          -- Add some SmallEiffel/sys/runtime/basic_* package as 
  1196.          -- an already used one in order to customize the runtime.
  1197.       require
  1198.          name.has_prefix("basic_")
  1199.       local
  1200.          package: STRING;
  1201.       do
  1202.          from
  1203.             package := "basic_....................";
  1204.             package.copy(name);
  1205.          until
  1206.             package.nb_occurrences('_') = 1
  1207.          loop
  1208.             package.remove_last(1);
  1209.          end;
  1210.          if not basic_sys_runtime.has(package) then
  1211.             package := package.twin;
  1212.             basic_sys_runtime.add_last(package);
  1213.          end;
  1214.       end;
  1215.  
  1216. feature {CONVERSION_HANDLER}
  1217.  
  1218.    reference_to_expanded(source_type: TYPE) is
  1219.       require
  1220.          source_type.is_reference
  1221.       local
  1222.          i: INTEGER;
  1223.          rc: RUN_CLASS;
  1224.          type: TYPE;
  1225.       do
  1226.          from
  1227.             i := 1;
  1228.          until
  1229.             i > run_class_dictionary.count
  1230.          loop
  1231.             rc := run_class_dictionary.item(i);
  1232.             type := rc.current_type;
  1233.             if type.is_expanded then
  1234.                if type.is_a(source_type) then
  1235.                   type := type.actual_reference(source_type);
  1236.                   rc := type.run_class;
  1237.                   if not rc.at_run_time then
  1238.                      rc.set_at_run_time;
  1239.                      source_type.run_class.falling_down;
  1240.                   end;
  1241.                else
  1242.                   eh.cancel;
  1243.                end;
  1244.             end;
  1245.             i := i + 1;
  1246.          end;
  1247.       end;
  1248.  
  1249. feature {NONE}
  1250.  
  1251.    basic_sys_runtime: FIXED_ARRAY[STRING] is
  1252.          -- Actually used packages of SmallEiffel/sys/runtime.
  1253.          -- For example: basic_directory, basic_time, basic_*, etc.
  1254.       once
  1255.          !!Result.with_capacity(12);
  1256.       end;
  1257.    
  1258.    string_at_run_time: BOOLEAN is
  1259.       require
  1260.          is_ready
  1261.       local
  1262.          rc: RUN_CLASS;
  1263.       do
  1264.          if run_class_dictionary.has(as_string) then
  1265.             rc := run_class_dictionary.at(as_string);
  1266.             Result := rc.at_run_time;
  1267.          end;
  1268.       end;
  1269.  
  1270.    singleton_memory: SMALL_EIFFEL is
  1271.       once
  1272.          Result := Current;
  1273.       end;
  1274.  
  1275. invariant
  1276.  
  1277.    is_real_singleton: Current = singleton_memory
  1278.  
  1279. end -- SMALL_EIFFEL
  1280.